package cn.kys.modules.system.service.impl;


import cn.kys.common.utils.UUIDStringUtil;
import cn.kys.modules.system.repository.ToolsResposity;
import cn.kys.modules.system.service.PhoneService;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.gridfs.GridFSBucket;
import com.mongodb.client.gridfs.GridFSBuckets;
import com.mongodb.client.gridfs.GridFSDownloadStream;
import com.mongodb.client.gridfs.GridFSFindIterable;
import com.mongodb.client.gridfs.model.GridFSFile;
import org.apache.commons.io.FileUtils;
import org.bson.Document;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.mongodb.gridfs.GridFsResource;
import org.springframework.data.mongodb.gridfs.GridFsTemplate;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
//import sun.misc.BASE64Encoder;
import org.apache.commons.codec.binary.Base64;
import sun.misc.BASE64Encoder;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.*;

@Service
public class PhoneServiceImpl implements PhoneService {
    @Autowired
    private ToolsResposity toolsResposity;

    @Autowired
    MongoTemplate mongoTemplate;

    @Value("${file.tempJpgFile}")
    private String tempJpgFile;

    @Autowired
    GridFsTemplate gridFsTemplate;

    private SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
    private SimpleDateFormat sdf_ = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    @Override
    public List getTasks() {
        String sql = "SELECT * FROM public.t_task where is_public = "+true;
        List list = toolsResposity.exeSqlList(sql);
        return list;
    }

    @Override
    public Map getDK(String taskid,String idCard, String caseid) {

        Map returnMap = new HashMap();

        String sql = "SELECT * FROM public.t_card where id_card = '"+idCard+"'";
        List listCard = toolsResposity.exeSqlList(sql);


        if(listCard.size()==0){

            returnMap.put("hasCard",false);
            returnMap.put("msg","没有上传身份证，请上传身份证正反面照片！");
        }else if(listCard.size()==1){
            Map mapCard = (Map)listCard.get(0);
            String type = mapCard.get("type").toString();
            String msg = "";
            if("idcard_front".equals(type)){
                msg = "反面照片";
            }else {
                msg = "正面照片";
            }
            returnMap.put("msg","请上传"+msg);
            returnMap.put("hasCard",false);
        }else {
            String sql_case = "SELECT * FROM public.t_case_editlayer where caseid = '"+caseid+"'";
            Map mapCase = toolsResposity.exeSql(sql_case);
            //td_dk_ks_4490
            String layername = mapCase.get("layername").toString();

            String sql_dk = "SELECT *,st_astext(ST_Transform(geom,4490)) FROM "+layername+" where cbfsfzh = '"+idCard+"'";
            List dkList = toolsResposity.exeSqlList(sql_dk);
            List dkListStatus = new ArrayList();
            for(int i=0;i<dkList.size();i++){
                Map dkMap = (Map) dkList.get(i);
                String cbfsfzh = dkMap.get("cbfsfzh").toString();
                String gid = dkMap.get("gid").toString();

                //存储表单信息
                Criteria criteria = Criteria.where("metadata.globle_gid").is(gid);
                criteria.and("metadata.globle_idcard").is(idCard);
                criteria.and("metadata.globle_taskid").is(taskid);
                Query query = new Query(criteria);
                boolean existed = mongoTemplate.exists(query, JSONObject.class,"phoneTable");

                if(existed){

                    Map mapTable = mongoTemplate.findOne(query, JSONObject.class,"phoneTable");
                    dkMap.put("status",mapTable);
                }

                dkMap.put("existed",existed);
                dkListStatus.add(dkMap);
            }


            String sql_form_content = "SELECT t1.*,t2.enum FROM public.t_form_content  t1  left join t_formcontent t2 ON t1.formcontentid=t2.id where formid in (SELECT formid FROM t_case_form where caseid = "+caseid+") order by t1.ordernum;";
            List form_content = toolsResposity.exeSqlList(sql_form_content);

            returnMap.put("hasCard",true);
            returnMap.put("dkList",filterList(dkListStatus));
            returnMap.put("form_content",form_content);
        }


        return returnMap;
    }

    @Override
    public void submitTableContent(String idCard, String taskId,String gid, String content) {
        //保存内容到mongodb
        try {
            //存储表单信息
            Criteria criteria = Criteria.where("metadata.globle_gid").is(gid);
            criteria.and("metadata.globle_idcard").is(idCard);
            criteria.and("metadata.globle_taskid").is(taskId);
            Query query = new Query(criteria);
            boolean existed = mongoTemplate.exists(query, JSONObject.class,"phoneTable");

            if(existed){
                //删除原来的
                mongoTemplate.remove(query, "phoneTable");
            }
            JSONObject jsonObject = (JSONObject) JSON.parse(content);
            if(jsonObject.containsKey("_id")){
                jsonObject.remove("_id");
            }
            String create_time = sdf_.format(new Date());
            Map metadata = new HashMap<>();
            metadata.put("globle_gid", gid);
            metadata.put("globle_idcard", idCard);
            metadata.put("globle_taskid", taskId);
            metadata.put("globle_status", "未审核");
            metadata.put("globle_create_time", create_time);
            metadata.put("globle_uuid", taskId+getUUID());
            jsonObject.put("metadata",metadata);

            mongoTemplate.save(jsonObject,"phoneTable");


        }catch (Exception e){
            e.printStackTrace();
        }
    }
    public String getUUID(){
        String str = UUID.randomUUID().toString().replaceAll("-", "");
        return str;
    }

    @Override
    public void updateStatus(String uuid, String status) {

        Criteria criteria = Criteria.where("metadata.globle_uuid").is(uuid);

        Query query = new Query(criteria);

        Update update = new Update().set("metadata.globle_status",status);
        mongoTemplate.updateFirst(query, update,"phoneTable");
    }

    @Override
    public Map submitCardImg(String idCard, MultipartFile uploadFile, String type) {

        Map returnMap = new HashMap();

        String sql = "select * from public.t_card where id_card = '"+idCard+"' and type = '"+type+"'";
        List cardList = toolsResposity.exeSqlList(sql);
        try{
            if(cardList.size()>0){
                returnMap.put("msg","身份证照片已经存在");
                returnMap.put("success",false);
            }else{
//                BASE64Encoder base64Encoder =new BASE64Encoder();
                String base64EncoderImg = uploadFile.getOriginalFilename()+","+ Base64.encodeBase64String(uploadFile.getBytes());
                String create_time = sdf_.format(new Date());
                String sql_insert = "INSERT INTO public.t_card(create_time,id_card,type,image_base64) VALUES ('" + create_time + "',"+idCard+",'"+type+"','"+base64EncoderImg+"');";
                toolsResposity.exeSql(sql_insert);
                returnMap.put("success",true);
            }


        }catch (Exception e){
            e.printStackTrace();
            returnMap.put("success",false);
        }

        return returnMap;
    }

    @Override
    public String submitTableFile(String globle_idcard,String globle_taskid,String globle_gid, String formcontentname, MultipartFile uploadFile, String alpha, String beta, String gamma, String lat, String lon) {
        String filename = null;
        try {
            //获取文件名
            String fileName = uploadFile.getOriginalFilename();
            //获取文件后缀名
            String suffixName = fileName.substring(fileName.lastIndexOf("."));
            //重新生成文件名
            fileName = UUID.randomUUID()+suffixName;
            //添加日期目录
            String format = sdf.format(new Date());
            //指定本地文件夹存储图片
            String filePath = "D:/images/"+format+"/";
            File file = new File(filePath,fileName);
            if (!file.getParentFile().exists()){
                file.getParentFile().mkdirs();
            }
            try {
                //图片保存
                file.createNewFile();
                uploadFile.transferTo(new File(filePath+fileName));
                filename = saveFile(file, UUIDStringUtil.getUUIDString(),formcontentname,globle_idcard,globle_taskid,globle_gid,alpha,beta,gamma,lat,lon);

            } catch (Exception e) {
                e.printStackTrace();

            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return filename;
    }

    @Override
    public List queryTableFile(String idCard,String taskid, String gid) {
        List returnList = new ArrayList();

        String base64 = null;

        String s = "";
        try{
            //根据id查询文件metadata.globle_gid
            Criteria criteria = Criteria.where("metadata.globle_idcard").is(idCard);
            criteria.and("metadata.globle_taskid").is(taskid);
            criteria.and("metadata.globle_gid").is(gid);
            Query query = new Query(criteria);
            GridFSFindIterable gridFSFiles =
                    gridFsTemplate.find(query);


            for (GridFSFile gridFSFile : gridFSFiles) {
                Map returnMap = new HashMap();
                Document metadataDocument = gridFSFile.getMetadata();

                String formcontentname = metadataDocument.get("globle_formcontentname").toString();
                String filename = metadataDocument.get("filename").toString();

                MongoDatabase mongoDatabase = mongoTemplate.getDb();
                GridFSBucket gridFSBucket = GridFSBuckets.create(mongoDatabase);
                //打开流下载对象
                GridFSDownloadStream downloadStream =
                        gridFSBucket.openDownloadStream(gridFSFile.getObjectId());
                //获取流对象
                GridFsResource gridFsResource = new GridFsResource(gridFSFile,downloadStream);

                //添加日期目录
                String format = sdf.format(new Date());
                //指定本地文件夹存储图片
//                String filePathDir = "D:/images/"+format;
                String filePathDir = tempJpgFile+format;
                File fileDir = new File(filePathDir);
//                String filePath = "D:/images/"+format+"/1.jpg";
                String filePath = tempJpgFile+format+File.separator+"1.jpg";
                File targetFile = new File(filePath);
                FileUtils.copyInputStreamToFile(gridFsResource.getInputStream(), targetFile);

                try {
                    base64 = convertFileToBase64(filePath);
                    returnMap.put("image",base64);
                    returnMap.put("formcontentname",formcontentname);
                    returnMap.put("filename",filename);
                    returnList.add(returnMap);
                    targetFile.delete();
                    fileDir.delete();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                System.out.println("打印文件:"+s);
            }

        }catch (Exception e){
            e.printStackTrace();
        }
        return returnList;
    }

    @Override
    public Map queryTables(String caseid,String idCard, String taskid,String gid) {

        Map returnMap = new HashMap();
        //结构
        String sql = "select * from t_form_content where formid in (SELECT formid FROM public.t_case_form where caseid = '"+caseid+"')";
        List structList = toolsResposity.exeSqlList(sql);
        returnMap.put("struct",structList);

        //内容
        Criteria criteria = Criteria.where("metadata.globle_idcard").is(idCard);
        criteria.and("metadata.globle_taskid").is(taskid);
        criteria.and("metadata.globle_gid").is(gid);
        Query query = new Query(criteria);
        List contentList = mongoTemplate.find(query, JSONObject.class,"phoneTable");
        if(contentList.size()==0){
            returnMap.put("hasContent",false);
        }else {
            returnMap.put("hasContent",true);
        }
        returnMap.put("content",contentList);

        return returnMap;
    }

    @Override
    public Map queryTablesPC(String taskid,String caseid,String status,int curPage, int pageSize) {
        Map returnMap = new HashMap();
        //结构
        String sql = "select * from t_form_content where formid in (SELECT formid FROM public.t_case_form where caseid = '"+caseid+"')";
        List structList = toolsResposity.exeSqlList(sql);
        returnMap.put("struct",structList);

        //内容return mongoTemplate.find(query.skip((curPage-1)*pageSize).limit(pageSize),Letter.class);

        Criteria criteria = Criteria.where("metadata.globle_taskid").is(taskid);
        if(!"".equals(status)){
            criteria.and("metadata.globle_status").is(status);
        }
        Query query = new Query(criteria);

        Criteria criteriaTotal = Criteria.where("metadata.globle_taskid").is(taskid);
        if(!"".equals(status)){
            criteriaTotal.and("metadata.globle_status").is(status);
        }

        Query queryTotal = new Query(criteriaTotal);
        List contentList = mongoTemplate.find(query.skip((curPage-1)*pageSize).limit(pageSize), JSONObject.class,"phoneTable");
        long count = mongoTemplate.count(queryTotal, "phoneTable");

        if(contentList.size()==0){
            returnMap.put("hasContent",false);
        }else {
            returnMap.put("hasContent",true);
        }
        returnMap.put("content",contentList);
        returnMap.put("count",count);
        return returnMap;
    }

    @Override
    public Map queryTablesPCByCard(String taskid, String caseid, String idCard,int curPage, int pageSize) {
        Map returnMap = new HashMap();
        //结构
        String sql = "select * from t_form_content where formid in (SELECT formid FROM public.t_case_form where caseid = '"+caseid+"')";
        List structList = toolsResposity.exeSqlList(sql);
        returnMap.put("struct",structList);

        //内容

        Criteria criteria = Criteria.where("metadata.globle_taskid").is(taskid);
        criteria.and("metadata.globle_idcard").is(idCard);
        Query query = new Query(criteria);
        List contentList = mongoTemplate.find(query.skip((curPage-1)*pageSize).limit(pageSize), JSONObject.class,"phoneTable");

        Criteria criteriaTotal = Criteria.where("metadata.globle_taskid").is(taskid);
        Query queryTotal = new Query(criteriaTotal);
        long count = mongoTemplate.count(queryTotal, "phoneTable");
        if(contentList.size()==0){
            returnMap.put("hasContent",false);
        }else {
            returnMap.put("hasContent",true);
        }
        returnMap.put("content",contentList);
        returnMap.put("count",count);
        return returnMap;
    }

    @Override
    public Map queryGeoAndImagePC(String idCard, String taskid, String caseid,String gid) {

        Map returnMap = new HashMap();

        String sql_case = "SELECT * FROM public.t_case_editlayer where caseid = '"+caseid+"'";
        Map mapCase = toolsResposity.exeSql(sql_case);
        //td_dk_ks_4490
        String layername = mapCase.get("layername").toString();

        String sql_dk = "SELECT *,st_astext(ST_Transform(geom,4490)) FROM "+layername+" where gid = '"+gid+"'";
        List dkList = toolsResposity.exeSqlList(sql_dk);
        returnMap.put("geo",filterList(dkList));

        //获取图片
        List returnList = new ArrayList();

        String base64 = null;

        String s = "";
        try{
            //根据id查询文件metadata.globle_gid
            Criteria criteria = Criteria.where("metadata.globle_idcard").is(idCard);
            criteria.and("metadata.globle_taskid").is(taskid);
            criteria.and("metadata.globle_gid").is(gid);
            Query query = new Query(criteria);
            GridFSFindIterable gridFSFiles =
                    gridFsTemplate.find(query);


            for (GridFSFile gridFSFile : gridFSFiles) {
                Map tempMap = new HashMap();
                Document metadataDocument = gridFSFile.getMetadata();

                String formcontentname = metadataDocument.get("globle_formcontentname").toString();
                String filename = metadataDocument.get("filename").toString();
                String alpha = metadataDocument.get("alpha").toString();
                String beta = metadataDocument.get("beta").toString();
                String gamma = metadataDocument.get("gamma").toString();
                String lat = metadataDocument.get("lat").toString();
                String lon = metadataDocument.get("lon").toString();

                MongoDatabase mongoDatabase = mongoTemplate.getDb();
                GridFSBucket gridFSBucket = GridFSBuckets.create(mongoDatabase);
                //打开流下载对象
                GridFSDownloadStream downloadStream =
                        gridFSBucket.openDownloadStream(gridFSFile.getObjectId());
                //获取流对象
                GridFsResource gridFsResource = new GridFsResource(gridFSFile,downloadStream);


                //添加日期目录
                String format = sdf.format(new Date());
                //指定本地文件夹存储图片
                String filePathDir = tempJpgFile +format;
                File fileDir = new File(filePathDir);
//                String filePath = "D:/images/"+format+"/1.jpg";
                String filePath = tempJpgFile + format + File.separator+"1.jpg";

                File targetFile = new File(filePath);
                FileUtils.copyInputStreamToFile(gridFsResource.getInputStream(), targetFile);

                try {
                    base64 = convertFileToBase64(filePath);
                    tempMap.put("image",base64);
                    tempMap.put("formcontentname",formcontentname);
                    tempMap.put("filename",filename);
                    tempMap.put("alpha",alpha);
                    tempMap.put("beta",beta);
                    tempMap.put("gamma",gamma);
                    tempMap.put("lat",lat);
                    tempMap.put("lon",lon);

                    returnList.add(tempMap);
                    targetFile.delete();
                    fileDir.delete();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                System.out.println("打印文件:"+s);
            }

        }catch (Exception e){
            e.printStackTrace();
        }
        returnMap.put("image",returnList);

        //获取身份证
        String sql_card = "SELECT * FROM public.t_card where id_card = '"+idCard+"'";
        List cardList = toolsResposity.exeSqlList(sql_card);
        returnMap.put("card",cardList);

        return returnMap;
    }

    @Override
    public void deleteImages(String idCard, String taskid, String gid) {
        Criteria criteria = Criteria.where("metadata.globle_idcard").is(idCard);
        criteria.and("metadata.globle_taskid").is(taskid);
        criteria.and("metadata.globle_gid").is(gid);
        Query query = new Query(criteria);
        gridFsTemplate.delete(query);
    }

    @Override
    public void deleteImage(String filename) {
        Criteria criteria = Criteria.where("metadata.filename").is(filename);
        Query query = new Query(criteria);
        gridFsTemplate.delete(query);
    }

    @Override
    public void deleteTable(String uuid) {

        Criteria criteria = Criteria.where("metadata.globle_uuid").is(uuid);
        Query query = new Query(criteria);
        boolean existed = mongoTemplate.exists(query, JSONObject.class,"phoneTable");

        if(existed){

            mongoTemplate.remove(query, "phoneTable");
        }
    }

    public  String saveFile( File file, String fileid,String formcontentname,String globle_idcard,String globle_taskid,String globle_gid,
                             String alpha,String beta,String gamma,String lat,String lon) {
        String filename = null;
        try {
            // 设置meta数据值
            Map<String, String> metaData = new HashMap<>();
            metaData.put("globle_idcard", globle_idcard);
            metaData.put("globle_taskid", globle_taskid);
            metaData.put("globle_gid", globle_gid);
            metaData.put("globle_formcontentname", formcontentname);
            metaData.put("filename", fileid);
            metaData.put("alpha", alpha);
            metaData.put("beta", beta);
            metaData.put("gamma", gamma);
            metaData.put("lat", lat);
            metaData.put("lon", lon);


            FileInputStream fileInputStream = new FileInputStream(file);//与根据File类对象的所代表的实际文件建立链接创建fileInputStream对象

            // 获取文件的源名称
            String fileName = file.getAbsoluteFile().getName();
            // 进行文件存储
            ObjectId objectId = gridFsTemplate.store(fileInputStream, fileName, metaData);

            //查询filename,根据objectId
            Criteria criteria = Criteria.where("_id").is(objectId.toString());
            Query query = new Query(criteria);
            GridFSFile gridFSFile = gridFsTemplate.findOne(query);
            Map map = gridFSFile.getMetadata();
            filename = map.get("filename").toString();
            System.out.println(objectId);
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("存储文件时发生错误！！！");
        }

        return filename;
    }

    private List filterList(List list) {

        List returnList = new ArrayList();

        for(int i=0;i<list.size();i++){
            Map returnMap = (Map)list.get(i);

            String st_astext = returnMap.get("st_astext").toString();

            List listPolygon = new ArrayList();

            if (st_astext.contains("MULTIPOLYGON")) {
                st_astext = st_astext.substring(15, st_astext.length() - 3);
            } else {
                st_astext = st_astext.substring(9, st_astext.length() - 2);
            }

            String[] polygons = st_astext.split("\\)\\), \\(\\(");

            for (int j = 0; j < polygons.length; j++) {
                String polygon = polygons[j].trim();
                if (polygon.contains("),(")) {
                    String[] polygonHole = polygon.split("\\),\\(");
                    listPolygon.add(polygonHole);
                } else {
                    listPolygon.add(polygon);
                }
            }

            returnMap.put("geo", listPolygon);

            returnList.add(returnMap);
        }

        return returnList;

    }
    /**
     * 本地文件（图片、excel等）转换成Base64字符串
     *
     * @param imgPath
     */
    public String convertFileToBase64(String imgPath) {
        byte[] data = null;
        // 读取图片字节数组
        try {
            InputStream in = new FileInputStream(imgPath);
            System.out.println("文件大小（字节）="+in.available());
            data = new byte[in.available()];
            in.read(data);
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 对字节数组进行Base64编码，得到Base64编码的字符串
        BASE64Encoder encoder = new BASE64Encoder();
        String base64Str = encoder.encode(data);
        return base64Str;
    }
}

